package com.hucsmn.examsystem.session;

import com.hucsmn.examsystem.common.AnswerSheet;
import com.hucsmn.examsystem.common.Problem;
import com.hucsmn.examsystem.server.ExamServerException;

import java.time.Instant;

/**
 * 会话状态。
 */
public class Session {
    private final int uid;
    private final boolean admin;
    private AnswerSheet answerSheet = null;
    private long begin;
    private int recentAnswerSheet = -1;

    public Session(int uid, boolean admin) {
        if (uid < 0) {
            throw new IllegalArgumentException("negative user id");
        }
        this.uid = uid;
        this.admin = admin;
    }

    public int getUid() {
        return uid;
    }

    public boolean isAdmin() {
        return admin;
    }

    public synchronized boolean isExamBegin() {
        return answerSheet != null;
    }

    public synchronized AnswerSheet beginExam(AnswerSheet answerSheet) throws ExamServerException {
        if (answerSheet == null) {
            throw new NullPointerException();
        }
        this.answerSheet = answerSheet;
        AnswerSheet withoutAnswers;
        try {
            withoutAnswers = (AnswerSheet) answerSheet.clone();
        } catch (CloneNotSupportedException e) {
            throw new ExamServerException(e);
        }
        for (Problem problem : withoutAnswers.getProblems()) {
            problem.setAnswers();
            problem.setToggled();
        }
        this.begin = Instant.now().getEpochSecond();
        return withoutAnswers;
    }

    public synchronized AnswerSheet endExam(AnswerSheet toggledAnswerSheet) throws ExamServerException {
        if (this.answerSheet == null) {
            throw new ExamServerException("exam not began or cancelled");
        }
        if (!this.answerSheet.equals(toggledAnswerSheet)) {
            throw new ExamServerException("mismatched problems or scores in the answer sheet");
        }

        long timestamp = Instant.now().getEpochSecond();
        long duration = timestamp - this.begin;
        toggledAnswerSheet.setUid(getUid());
        toggledAnswerSheet.setDuration(duration);
        toggledAnswerSheet.setSubmitTime(timestamp);

        Problem[] dst = toggledAnswerSheet.getProblems();
        Problem[] src = answerSheet.getProblems();
        for (int i = 0; i < dst.length; i++) {
            dst[i].setAnswers(src[i].getAnswers());
        }

        this.answerSheet = null;
        this.begin = 0;
        return toggledAnswerSheet;
    }

    public synchronized void cancelExam() {
        this.answerSheet = null;
        this.begin = 0;
    }

    public int getRecentAnswerSheet() {
        return recentAnswerSheet;
    }

    public synchronized void setRecentAnswerSheet(int recentAnswerSheet) {
        this.recentAnswerSheet = recentAnswerSheet;
    }
}
